package com.version1_2.dao.implement;

import com.SQLGroup.SQLAccess;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mysql.jdbc.Statement;
import com.util.property.Properties;
import com.version1_1.dao.PageDao;
import com.version1_1.model.MainPageModel;
import com.version1_2.dao.PageDao1_2;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.*;

@Repository
public class PageDao12Impl implements PageDao1_2 {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private PageDao pageDao; //复用pageDao中一些方法

    /*logger使用对象创建*/
    private static final Logger LOGGER = Logger.getLogger(PageDao12Impl.class);


    /**
     * @description: 在数据库中更新评论的点赞数或者新增一条评论（包括回复）
     */
    @Override
    public boolean setPageComPraise(JSONObject jsonObject) {
        int commentType = jsonObject.getIntValue("commentType");
        int result = 0;

        switch (commentType) {
            case -1:
                /**
                 * 1. 取消对一条评论的点赞
                 * {"commentType":1,"commentId":,"senderId":,"receiverId":,"date":""}
                 */
                int commentId = jsonObject.getIntValue("commentId");
                int senderId1 = jsonObject.getIntValue("senderId");

                try {
                    result = jdbcTemplate.update(SQLAccess.DeleteACommnetPraise, new Object[]{commentId, senderId1});
                } catch (DataAccessException exception) {
                    LOGGER.error("取消对一条评论的点赞出错...", exception);
                }
                break;
            case 1:
                /**
                 * 2. 对一条评论进行点赞
                 */
                int comId = jsonObject.getIntValue("commentId");
                int senderId = jsonObject.getIntValue("senderId");
                int receiverId = jsonObject.getIntValue("receiverId");
                String date = jsonObject.getString("date");

                try {
                    result = jdbcTemplate.update(SQLAccess.AddACommentPraise, new Object[]{comId, senderId, receiverId, date});
                } catch (DataAccessException exception) {
                    LOGGER.error("对一条评论进行点赞出错...", exception);
                }
                break;

            default:
                break;
        }

        return result == 0 ? false : true;
    }

    /**
     * @Description: 新增一条评论或回复
     */
    @Override
    public int setPageComment(JSONObject jsonObject) {
        KeyHolder key = new GeneratedKeyHolder();
        jdbcTemplate.update(new PreparedStatementCreator() {

            @Override
            public PreparedStatement createPreparedStatement(Connection conn)
                    throws SQLException {

                PreparedStatement preStatement = conn.prepareStatement(
                        SQLAccess.AddACommnet, Statement.RETURN_GENERATED_KEYS);
                preStatement.setInt(1, jsonObject.getIntValue("pageId"));
                preStatement.setInt(2, jsonObject.getIntValue("senderId"));
                preStatement.setInt(3, jsonObject.getIntValue("toComId"));
                preStatement.setString(4, jsonObject.getString("date"));
                preStatement.setString(5, jsonObject.getString("comment"));
                return preStatement;
            }
        }, key);

        // 如果这是一条回复则更新原来的评论的hasReply为1
        if (jsonObject.getIntValue("toComId") != -1) {
            int updateRow = jdbcTemplate.update(SQLAccess.UpdateHasreplyTrue, new Object[]{jsonObject.getIntValue("toComId")});
            if (updateRow == 0) {
                LOGGER.error("新增评论或回复，改变原先评论的hasReply为1出错");
            }
        }
        return key.getKey().intValue();
    }


    /**
     * @Description: 页面标题搜索
     */
    @Override
    public List<Map<String, Object>> searchPage(String key) {
        String sql = "SELECT pageId,firstTitle AS pageTitle,secondType,thirdTypeName,imageSrc FROM pagepre_firsttype WHERE firstTitle LIKE '%" + key + "%'";
        return jdbcTemplate.queryForList(sql);
    }


    /**
     * @Description: 获取除正文之外其他信息
     */
    @Override
    public Map<String, Object> getPageOtherInfo(int userId, int pageId) {
        String sql = "";

        Map<String, Object> pageOtherInfoMap = new HashMap<>();

        /**
         * 根据pageId取出praNum,criNum,typeId,并根据typeId判断用户是否订阅了此分类
         */
        boolean isSubscri = false;

        sql = "SELECT praNum,criNum,typeId FROM page_info WHERE pageId=?";
        Map<String, Object> queryMap1 = jdbcTemplate.queryForMap(sql, new Object[]{pageId});

        // 兼容version1_2和version1_3接口
        sql = "SELECT thirdTypeId,thirdTypeName,typeBgImgSrc FROM type_info WHERE id=?";
        Map<String, Object> queryMap0 = jdbcTemplate.queryForMap(sql, new Object[]{(int) queryMap1.get("typeId")});
        String thirdTypeName = (String) queryMap0.get("thirdTypeName");

        sql = "SELECT userFocusId FROM user_info WHERE userId=?";

        String userFocusId = "";
        try {
            userFocusId = jdbcTemplate.queryForObject(sql, new Object[]{userId}, String.class);
        } catch (EmptyResultDataAccessException exception) {
            LOGGER.info("未登陆用户请求除html页面外的其他信息...");
        }

        // 兼容version1_2和version1_3接口
        if (userFocusId.contains(thirdTypeName) || userFocusId.contains(String.valueOf(queryMap0.get("thirdTypeId")))) {
            isSubscri = true;
        }

        //--------------------到了添加数据的时候-----------------//
        pageOtherInfoMap.put("praNum", (int) queryMap1.get("praNum"));
        pageOtherInfoMap.put("criNum", (int) queryMap1.get("criNum"));
        pageOtherInfoMap.put("typeBgImgSrc", (String) queryMap0.get("typeBgImgSrc"));
        pageOtherInfoMap.put("adPicUrl", Properties.Page_adPicUrl);
        pageOtherInfoMap.put("adLink", "null");
        pageOtherInfoMap.put("isSubscri", isSubscri);

        /**
         * 从info_comment得到用户是否对该篇文章点击好文或者水文
         */
        int userChoice = -1;
        sql = "SELECT id,choice FROM info_comment WHERE userId=? AND pageId=?";
        try {
            // 防止info_comment有多个userId=-1而pageId相同的记录造成查询出错
            int userIdTemp = 0;
            if (userId != -1) {
                userIdTemp = userId;
            }

            Map<String, Object> queryMap2 = jdbcTemplate.queryForMap(sql, new Object[]{userIdTemp, pageId});
            userChoice = (int) queryMap2.get("choice");
        } catch (EmptyResultDataAccessException ex) {
            LOGGER.info("从info_comment中无法找到用户: " + userId + " 对pageId为：" + pageId + " 的文章的评价");
        }

        //--------------------到了添加数据的时候-----------------//
        pageOtherInfoMap.put("userChoice", userChoice);

        /**
         * 获取推荐文章列表,文章是随机的
         */
        List<Map<String, Object>> recomList = new ArrayList<>();

        try {
            recomList = jdbcTemplate.queryForList(SQLAccess.SelectRecommendPageVersion1_2, new Object[]{(int) queryMap1.get("typeId")});
        } catch (EmptyResultDataAccessException exception) {
            LOGGER.error("获取推荐文章出错，没有找到数据");
        }

        //--------------------到了添加数据的时候-----------------//
        pageOtherInfoMap.put("recomArtc", recomList);

        /**
         * 获取评论列表
         */
        List<Map<String, Object>> commentList = jdbcTemplate.queryForList(SQLAccess.SelectFirstPageComment, new Object[]{pageId, Properties.PageSize_PageComment});


        for (int i = 0; i < commentList.size(); i++) {
            commentList.get(i).put("hasPraised", pageDao.checkPraised((int) commentList.get(i).get("commentId"), userId));
        }

        //--------------------到了添加数据的时候-----------------//
        pageOtherInfoMap.put("comFirPage", commentList);


        /**
         * 获取评论总条数
         */
        int commentNum = jdbcTemplate.queryForObject(SQLAccess.SelectPageCommentCount, new Object[]{pageId}, Integer.class);

        //--------------------到了添加数据的时候-----------------//
        pageOtherInfoMap.put("comNum", commentNum);

        return pageOtherInfoMap;
    }


    /**
     * @description: 获取登陆用户主界面信息
     */
    @Override
    public MainPageModel getNewMainPage(int userId, int firstType, int pageNumber, int pageSize) {
        List mainPageList = null;
        List<Integer> userFocusTypeList = null;
        List titleList = null;
        boolean isLast = false;

        try {
            userFocusTypeList = pageDao.getUserFocusId(userId, firstType);
        } catch (Exception ex) {
            LOGGER.error("查询用户关注分类信息错误", ex);
        }

        //如果用户一级分类下关注信息为空
        if (userFocusTypeList.isEmpty()) {
            LOGGER.info("用户一级分类下关注信息为空,firstType: " + firstType + ", userId: " + userId);
        } else {
            // 对list进行升序排序
            Collections.sort(userFocusTypeList);

            // 对于兴趣分类降序排序,将跬步有曰放在最后
            if (firstType == 5) {
                Collections.reverse(userFocusTypeList);
            }

            int count = (userFocusTypeList.size() % pageSize == 0) ? userFocusTypeList.size() / pageSize : userFocusTypeList.size() / pageSize + 1;

            if (pageNumber > count) {
                LOGGER.info("用户请求分页数过大,pageNumber= " + pageNumber + ",count: " + count);
            } else {
                int begin = pageSize * (pageNumber - 1);
                int end = pageSize * (pageNumber);
                if (userFocusTypeList.size() <= pageSize * (pageNumber)) {
                    end = userFocusTypeList.size();
                }

                mainPageList = new ArrayList<>();
                for (int i = begin; i < end; i++) {

                    // 这里使用了缓存方法
                    List tempList = getThirdInfo(userFocusTypeList.get(i), Properties.PageSize_MainPagePerThrid);
                    mainPageList.addAll(tempList);
                }
            }
        }


        if (mainPageList == null || mainPageList.isEmpty()) {
            isLast = true;
        }

        if (pageNumber == 1) {
            titleList = getTitleList(firstType);
        }

        return new MainPageModel(mainPageList, isLast, titleList);
    }

    /**
     * @description: 得到未登陆用户的主界面信息
     */
    @Override
    public MainPageModel getNewPageListNoLogin(JSONObject jsonObject, int pageNumber,
                                               int pageSize) {
        List mainPageList = null;
        boolean isLast = false;
        List titleList = null;
        List<Integer> focusTypeIdList = new ArrayList<>();

        JSONArray jsonArray = jsonObject.getJSONArray("mainFocusList");

        int k = 0;
        try {
            for (k = 0; k < jsonArray.size(); k++) {
                int id = jdbcTemplate.queryForObject(SQLAccess.SelectThirdTypeId, new Object[]{
                                jsonArray.getJSONObject(k).getIntValue("secondType"),
                                jsonArray.getJSONObject(k).getString("thirdName")},
                        Integer.class);
                focusTypeIdList.add(id);
            }
        } catch (EmptyResultDataAccessException exception) {
            LOGGER.error("得到未登陆用户的主界面一级分类下的预览信息数据错误,mainFocusList: \n" + jsonObject.toJSONString() + "\n");
        }

        if (focusTypeIdList.isEmpty()) {
            LOGGER.info("关注分类数为0...");
        } else {
            // 对list进行升序排序
            Collections.sort(focusTypeIdList);

            int count = (focusTypeIdList.size() % pageSize == 0) ? focusTypeIdList.size() / pageSize : focusTypeIdList.size() / pageSize + 1;

            if (pageNumber > count) {
                LOGGER.info("用户请求分页数过大...");
            } else {
                int begin = pageSize * (pageNumber - 1);
                int end = pageSize * (pageNumber);
                if (focusTypeIdList.size() <= pageSize * (pageNumber)) {
                    end = focusTypeIdList.size();
                }

                mainPageList = new ArrayList<>();
                for (int i = begin; i < end; i++) {

                    // 使用了缓存方法
                    List tempList = getThirdInfo(focusTypeIdList.get(i), Properties.PageSize_MainPagePerThrid);
                    mainPageList.addAll(tempList);
                }
            }
        }

        if (mainPageList == null || mainPageList.isEmpty()) {
            isLast = true;
        }

        if (pageNumber == 1) {
            titleList = getTitleList(jsonObject.getIntValue("itemNumber"));
        }

        return new MainPageModel(mainPageList, isLast, titleList);
    }

    /**
     * @description: 获取三级分类页面预览信息数据
     */
    @Override
    public List getThirdPageList(int secondType, String thirdTypeName,
                                 int pageNumber, int pageSize) {

        @SuppressWarnings("deprecation")
        int count = jdbcTemplate.queryForInt(SQLAccess.SelectAThirdTypeInfoCount, new Object[]{
                secondType, thirdTypeName});
        if ((pageNumber - 1) * pageSize >= count) {
            LOGGER.info("获取三级分类页面预览信息数据,用户请求分页数过大...");
            return null;
        }

        return jdbcTemplate.queryForList(SQLAccess.SelectAThirdTypePageInfoVersion1_2, new Object[]{
                secondType, thirdTypeName, (pageNumber - 1) * pageSize,
                pageSize});
    }


    /**
     * @description: 获取主界面大图信息数组
     */
    @Override
    @Cacheable(value = {"pageTitleVersion1_2"})
    public List getTitleList(int firstType) {
        //大图信息数组
        List titleList = null;
        try {
            titleList = jdbcTemplate.queryForList(SQLAccess.SelectFirstTypeSlideInfoVersion1_2, new Object[]{firstType, Properties.TitlePic_Num});
        } catch (EmptyResultDataAccessException exception) {
            LOGGER.error("获取主界面大图信息数组,未查询到大图信息,EmptyResultDataAccessException...", exception);
        }
        return titleList;
    }

    /*
    * 工具类方法
    */

    /**
     * 获取主界面上一个三级分类的信息
     */
    @Cacheable(value = {"thirdTypePageVersion1_2"})
    public List getThirdInfo(int typeId, int pageSize) {
        return jdbcTemplate.queryForList(SQLAccess.SelectAThirdTypeInfoVersion1_2, new Object[]{typeId, pageSize});
    }
}
